//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.quickserver.net.server;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.net.BindException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.quickserver.net.AppException;
import org.quickserver.net.InitServerHook;
import org.quickserver.net.ServerHook;
import org.quickserver.net.Service;
import org.quickserver.net.qsadmin.QSAdminServer;
import org.quickserver.net.server.gui.About;
import org.quickserver.net.server.impl.DefaultClientEventHandler;
import org.quickserver.net.server.impl.RegisterChannelRequest;
import org.quickserver.security.SecureStoreManager;
import org.quickserver.sql.DBPoolUtil;
import org.quickserver.util.Assertion;
import org.quickserver.util.ClassUtil;
import org.quickserver.util.MyString;
import org.quickserver.util.TextFile;
import org.quickserver.util.io.ByteBufferInputStream;
import org.quickserver.util.io.ByteBufferOutputStream;
import org.quickserver.util.pool.ByteBufferObjectFactory;
import org.quickserver.util.pool.ClientHandlerObjectFactory;
import org.quickserver.util.pool.PoolHelper;
import org.quickserver.util.pool.PoolableObject;
import org.quickserver.util.pool.QSObjectPool;
import org.quickserver.util.pool.QSObjectPoolMaker;
import org.quickserver.util.pool.thread.ClientPool;
import org.quickserver.util.pool.thread.ThreadObjectFactory;
import org.quickserver.util.xmlreader.AccessConstraintConfig;
import org.quickserver.util.xmlreader.BasicServerConfig;
import org.quickserver.util.xmlreader.ConfigReader;
import org.quickserver.util.xmlreader.DBObjectPoolConfig;
import org.quickserver.util.xmlreader.DefaultDataMode;
import org.quickserver.util.xmlreader.InitServerHooks;
import org.quickserver.util.xmlreader.PoolConfig;
import org.quickserver.util.xmlreader.QSAdminServerConfig;
import org.quickserver.util.xmlreader.QuickServerConfig;
import org.quickserver.util.xmlreader.Secure;
import org.quickserver.util.xmlreader.ServerHooks;

public class QuickServer implements Runnable, Service, Cloneable, Serializable {
    private static final String VER = "2.0.0";
    private static final String NEW_LINE;
    private static final String pid;
    private String serverBanner;
    private String clientAuthenticationHandlerString;
    private String clientEventHandlerString;
    private String clientExtendedEventHandlerString;
    private String clientCommandHandlerString;
    private String clientObjectHandlerString;
    private String clientBinaryHandlerString;
    private String clientWriteHandlerString;
    private String clientDataString;
    private Authenticator authenticator;
    private ClientAuthenticationHandler clientAuthenticationHandler;
    private ClientEventHandler clientEventHandler;
    private ClientExtendedEventHandler clientExtendedEventHandler;
    private ClientCommandHandler clientCommandHandler;
    private ClientObjectHandler clientObjectHandler;
    private ClientBinaryHandler clientBinaryHandler;
    private ClientWriteHandler clientWriteHandler;
    private ClientData clientData;
    protected Class clientDataClass;
    private int serverPort;
    private Thread t;
    protected ServerSocket server;
    private String serverName;
    private long maxConnection;
    private int socketTimeout;
    private String maxConnectionMsg;
    private String timeoutMsg;
    private String maxAuthTryMsg;
    private int maxAuthTry;
    private InetAddress ipAddr;
    protected boolean stopServer;
    private Object[] storeObjects;
    private QSAdminServer adminServer;
    private static final Logger logger;
    private Logger appLogger;
    private long suspendMaxConnection;
    private String suspendMaxConnectionMsg;
    private int serviceState;
    private QuickServerConfig config;
    private String consoleLoggingformatter;
    private String consoleLoggingLevel;
    private ClientPool pool;
    private ObjectPool clientHandlerPool;
    private ObjectPool clientDataPool;
    private DBPoolUtil dBPoolUtil;
    private String loggingLevel;
    private boolean skipValidation;
    private boolean communicationLogging;
    private String securityManagerClass;
    private AccessConstraintConfig accessConstraintConfig;
    private ClassLoader classLoader;
    private String applicationJarPath;
    private ServerHooks serverHooks;
    private ArrayList listOfServerHooks;
    private Secure secure;
    private BasicServerConfig basicConfig;
    private SSLContext sslc;
    private KeyManager[] km;
    private TrustManager[] tm;
    private boolean runningSecure;
    private SecureStoreManager secureStoreManager;
    private Exception exceptionInRun;
    private ServerSocketChannel serverSocketChannel;
    private Selector selector;
    private boolean blockingMode;
    private ObjectPool byteBufferPool;
    private Date lastStartTime;
    private ClientIdentifier clientIdentifier;
    private GhostSocketReaper ghostSocketReaper;
    private PoolManager poolManager;
    private QSObjectPoolMaker qsObjectPoolMaker;
    private DataMode defaultDataModeIN;
    private DataMode defaultDataModeOUT;
    private Throwable serviceError;
    private Map registerChannelRequestMap;
    private boolean rawCommunicationLogging;
    private int rawCommunicationMaxLength;
    private static final int SECOND = 1000;
    private static final int MINUTE = 60000;
    private static final int HOUR = 3600000;
    private static final int DAY = 86400000;

    static {
        if (System.getProperty("org.quickserver.useOSLineSeparator") != null && System.getProperty("org.quickserver.useOSLineSeparator").equals("true")) {
            NEW_LINE = System.getProperty("line.separator");
        } else {
            NEW_LINE = "\r\n";
        }

        String _pid = ManagementFactory.getRuntimeMXBean().getName();
        int i = _pid.indexOf("@");
        pid = _pid.substring(0, i);
        System.out.print("Loading QuickServer v" + getVersion() + " [PID:" + pid + "]");
        System.out.print(".");
        logger = Logger.getLogger(QuickServer.class.getName());
        System.out.print(".");
        System.out.print(".");
        System.out.println(" Done");
        logger.log(Level.FINE, "PID: {0}", pid);
    }

    public static final String getVersion() {
        return "2.0.0";
    }

    public static final float getVersionNo() {
        return getVersionNo("2.0.0");
    }

    public static final float getVersionNo(String ver) {
        float version = 0.0F;
        int i = ver.indexOf(" ");
        if (i == -1) {
            i = ver.length();
        }

        ver = ver.substring(0, i);
        i = ver.indexOf(".");
        if (i != -1) {
            int j = ver.indexOf(".", i);
            if (j != -1) {
                ver = ver.substring(0, i) + "." + MyString.replaceAll(ver.substring(i + 1), ".", "");
            }
        }

        try {
            version = Float.parseFloat(ver);
            return version;
        } catch (NumberFormatException var4) {
            throw new RuntimeException("Corrupt QuickServer");
        }
    }

    public static String getNewLine() {
        return NEW_LINE;
    }

    public String toString() {
        return this.serverName + " : " + this.getPort();
    }

    public QuickServer() {
        this.clientDataString = "org.quickserver.net.model.GBServerData";
        this.serverPort = 9876;
        this.serverName = "QuickServer";
        this.maxConnection = -1L;
        this.socketTimeout = 60000;
        this.maxConnectionMsg = "-ERR Server Busy. Max Connection Reached";
        this.timeoutMsg = "-ERR Timeout";
        this.maxAuthTryMsg = "-ERR Max Auth Try Reached";
        this.maxAuthTry = 5;
        this.serviceState = -1;
        this.config = new QuickServerConfig();
        this.consoleLoggingLevel = "INFO";
        this.loggingLevel = "INFO";
        this.skipValidation = false;
        this.communicationLogging = true;
        this.basicConfig = this.config;
        this.km = null;
        this.tm = null;
        this.runningSecure = false;
        this.secureStoreManager = null;
        this.exceptionInRun = null;
        this.blockingMode = true;
        this.defaultDataModeIN = DataMode.STRING;
        this.defaultDataModeOUT = DataMode.STRING;
        this.rawCommunicationLogging = false;
        this.rawCommunicationMaxLength = 100;
    }

    public QuickServer(String commandHandler) {
        this.clientDataString = "org.quickserver.net.model.GBServerData";
        this.serverPort = 9876;
        this.serverName = "QuickServer";
        this.maxConnection = -1L;
        this.socketTimeout = 60000;
        this.maxConnectionMsg = "-ERR Server Busy. Max Connection Reached";
        this.timeoutMsg = "-ERR Timeout";
        this.maxAuthTryMsg = "-ERR Max Auth Try Reached";
        this.maxAuthTry = 5;
        this.serviceState = -1;
        this.config = new QuickServerConfig();
        this.consoleLoggingLevel = "INFO";
        this.loggingLevel = "INFO";
        this.skipValidation = false;
        this.communicationLogging = true;
        this.basicConfig = this.config;
        this.km = null;
        this.tm = null;
        this.runningSecure = false;
        this.secureStoreManager = null;
        this.exceptionInRun = null;
        this.blockingMode = true;
        this.defaultDataModeIN = DataMode.STRING;
        this.defaultDataModeOUT = DataMode.STRING;
        this.rawCommunicationLogging = false;
        this.rawCommunicationMaxLength = 100;
        this.setClientCommandHandler(commandHandler);
    }

    public QuickServer(String commandHandler, int port) {
        this(commandHandler);
        this.setPort(port);
    }

    public void startServer() throws AppException {
        logger.log(Level.FINE, "Starting {0}", this.getName());
        if (!this.isClosed()) {
            logger.log(Level.WARNING, "Server {0} already running.", this.getName());
            throw new AppException("Server " + this.getName() + " already running.");
        } else {
            this.blockingMode = this.getBasicConfig().getServerMode().getBlocking();
            if (this.getSecure().isEnable() && !this.blockingMode) {
                logger.warning("QuickServer does not support secure servers under non-blocking mode! So will run in blocking mode.");
                this.blockingMode = true;
                this.getBasicConfig().getServerMode().setBlocking(this.blockingMode);
            }

            if (this.serverBanner == null) {
                this.serverBanner = "\n-------------------------------\n Name : " + this.getName() + "\n Port : " + this.getPort() + "\n-------------------------------\n";
                logger.finest("Default Server Banner Generated");
            }

            try {
                this.loadApplicationClasses();
                Class clientIdentifierClass = this.getClass(this.getBasicConfig().getAdvancedSettings().getClientIdentifier(), true);
                this.clientIdentifier = (ClientIdentifier)clientIdentifierClass.newInstance();
                this.clientIdentifier.setQuickServer(this);
                Class poolManagerClass = this.getClass(this.getBasicConfig().getObjectPoolConfig().getPoolManager(), true);
                this.poolManager = (PoolManager)poolManagerClass.newInstance();
                Class qsObjectPoolMakerClass = this.getClass(this.getBasicConfig().getAdvancedSettings().getQSObjectPoolMaker(), true);
                this.qsObjectPoolMaker = (QSObjectPoolMaker)qsObjectPoolMakerClass.newInstance();
                this.loadServerHooksClasses();
                this.processServerHooks(100);
                if (this.getSecure().isLoad()) {
                    this.loadSSLContext();
                }

                this.loadBusinessLogic();
            } catch (ClassNotFoundException var4) {
                logger.log(Level.SEVERE, "Could not load class/s: " + var4, var4);
                throw new AppException("Could not load class/s : " + var4);
            } catch (InstantiationException var5) {
                logger.log(Level.SEVERE, "Could not instantiate class/s: " + var5, var5);
                throw new AppException("Could not instantiate class/s: " + var5);
            } catch (IllegalAccessException var6) {
                logger.log(Level.SEVERE, "Illegal access to class/s: " + var6, var6);
                throw new AppException("Illegal access to class/s: " + var6);
            } catch (IOException var7) {
                logger.log(Level.SEVERE, "IOException: " + var7, var7);
                throw new AppException("IOException: " + var7);
            } catch (Exception var8) {
                logger.log(Level.SEVERE, "Exception: " + var8, var8);
                logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(var8));
                throw new AppException("Exception : " + var8);
            }

            if (this.getSecurityManagerClass() != null) {
                System.setSecurityManager(this.getSecurityManager());
            }

            this.setServiceState(1);
            this.t = new Thread(this, "QuickServer - " + this.getName());
            this.t.start();

            do {
                Thread.yield();
            } while(this.getServiceState() == 1);

            if (this.getServiceState() != 5) {
                if (this.exceptionInRun != null) {
                    throw new AppException("Could not start server " + this.getName() + "! Details: " + this.exceptionInRun);
                } else {
                    throw new AppException("Could not start server " + this.getName());
                }
            } else {
                this.lastStartTime = new Date();
                logger.log(Level.FINE, "Started {0}, Date: {1}", new Object[]{this.getName(), this.lastStartTime});
            }
        }
    }

    public void stopServer() throws AppException {
        this.processServerHooks(201);
        logger.log(Level.WARNING, "Stopping {0}", this.getName());
        this.stopServer = true;
        Socket death = null;
        if (this.isClosed()) {
            logger.log(Level.WARNING, "Server {0} is not running!", this.getName());
            throw new AppException("Server " + this.getName() + " is not running!");
        } else {
            try {
                if (this.getBlockingMode()) {
                    if (!this.getSecure().isEnable()) {
                        death = new Socket(this.server.getInetAddress(), this.server.getLocalPort());
                        death.getInputStream().read();
                        death.close();
                    } else {
                        death = this.getSSLSocketFactory().createSocket(this.server.getInetAddress(), this.server.getLocalPort());
                        Thread.sleep(100L);
                        death.close();
                    }
                }

                if (this.serverSocketChannel != null) {
                    this.serverSocketChannel.close();
                }
            } catch (IOException var5) {
                logger.log(Level.FINE, "IOError stopping {0}: {1}", new Object[]{this.getName(), var5});
            } catch (Exception var6) {
                logger.log(Level.WARNING, "Error stopping {0}: {1}", new Object[]{this.getName(), var6});
                throw new AppException("Error in stopServer " + this.getName() + ": " + var6);
            }

            for(int i = 0; this.getServiceState() != 0; ++i) {
                try {
                    Thread.sleep(60L);
                } catch (Exception var4) {
                    logger.log(Level.WARNING, "Error waiting for {0} to fully stop. Error: {1}", new Object[]{this.getName(), var4});
                }

                if (i > 1000) {
                    logger.severe("Server was not stopped even after 10sec.. will terminate now.");
                    System.exit(-1);
                }
            }

            if (this.adminServer == null || this.getQSAdminServer().getServer() != this) {
                this.setClassLoader((ClassLoader)null);
            }

            logger.log(Level.INFO, "Stopped {0}", this.getName());
        }
    }

    public void restartServer() throws AppException {
        this.stopServer();
        this.startServer();
    }

    public String getName() {
        return this.serverName;
    }

    public void setName(String name) {
        this.serverName = name;
        logger.log(Level.FINEST, "Set to : {0}", name);
    }

    public String getServerBanner() {
        return this.serverBanner;
    }

    public void setServerBanner(String banner) {
        this.serverBanner = banner;
        logger.log(Level.FINEST, "Set to : {0}", banner);
    }

    public void setPort(int port) {
        if (port < 0) {
            throw new IllegalArgumentException("Port number can not be less than 0!");
        } else {
            this.serverPort = port;
            logger.log(Level.FINEST, "Set to {0}", port);
        }
    }

    public int getPort() {
        if (!this.isClosed()) {
            return this.server.getLocalPort();
        } else if (!this.getSecure().isEnable()) {
            return this.serverPort;
        } else {
            int _port = this.getSecure().getPort();
            return _port == -1 ? this.serverPort : _port;
        }
    }

    public void setClientCommandHandler(String handler) {
        this.clientCommandHandlerString = handler;
        logger.log(Level.FINEST, "Set to {0}", handler);
    }

    public String getClientCommandHandler() {
        return this.clientCommandHandlerString;
    }

    public void setClientAuthenticationHandler(String authenticator) {
        this.clientAuthenticationHandlerString = authenticator;
        logger.log(Level.FINEST, "Set to {0}", authenticator);
    }

    public String getClientAuthenticationHandler() {
        return this.clientAuthenticationHandlerString;
    }

    /** @deprecated */
    public void setAuthenticator(String authenticator) {
        this.clientAuthenticationHandlerString = authenticator;
        logger.log(Level.FINEST, "Set to {0}", authenticator);
    }

    /** @deprecated */
    public String getAuthenticator() {
        return this.clientAuthenticationHandlerString;
    }

    public void setClientData(String data) {
        this.clientDataString = data;
        logger.log(Level.FINEST, "Set to {0}", data);
    }

    public String getClientData() {
        return this.clientDataString;
    }

    public void setTimeout(int time) {
        if (time > 0) {
            this.socketTimeout = time;
        } else {
            this.socketTimeout = 0;
        }

        logger.log(Level.FINEST, "Set to {0}", this.socketTimeout);
    }

    public int getTimeout() {
        return this.socketTimeout;
    }

    public void setMaxAuthTry(int authTry) {
        this.maxAuthTry = authTry;
        logger.log(Level.FINEST, "Set to {0}", authTry);
    }

    public int getMaxAuthTry() {
        return this.maxAuthTry;
    }

    public void setMaxAuthTryMsg(String msg) {
        this.maxAuthTryMsg = msg;
        logger.log(Level.FINEST, "Set to {0}", msg);
    }

    public String getMaxAuthTryMsg() {
        return this.maxAuthTryMsg;
    }

    public void setTimeoutMsg(String msg) {
        this.timeoutMsg = msg;
        logger.log(Level.FINEST, "Set to {0}", msg);
    }

    public String getTimeoutMsg() {
        return this.timeoutMsg;
    }

    private TheClient initTheClient() {
        TheClient theClient = new TheClient();
        theClient.setServer(this);
        theClient.setTimeoutMsg(this.getTimeoutMsg());
        theClient.setMaxAuthTry(this.getMaxAuthTry());
        theClient.setMaxAuthTryMsg(this.getMaxAuthTryMsg());
        theClient.setClientEventHandler(this.clientEventHandler);
        theClient.setClientExtendedEventHandler(this.clientExtendedEventHandler);
        theClient.setClientCommandHandler(this.clientCommandHandler);
        theClient.setClientObjectHandler(this.clientObjectHandler);
        theClient.setClientBinaryHandler(this.clientBinaryHandler);
        theClient.setClientWriteHandler(this.clientWriteHandler);
        theClient.setAuthenticator(this.authenticator);
        theClient.setClientAuthenticationHandler(this.clientAuthenticationHandler);
        theClient.setTimeout(this.socketTimeout);
        theClient.setMaxConnectionMsg(this.maxConnectionMsg);
        theClient.setCommunicationLogging(this.getCommunicationLogging());
        return theClient;
    }

    public void run() {
        this.exceptionInRun = null;
        TheClient theClient = this.initTheClient();

        try {
            this.stopServer = false;
            this.closeAllPools();
            this.initAllPools();
            this.makeServerSocket();
            System.out.println(this.serverBanner);
            this.setServiceState(5);
            this.processServerHooks(101);
            if (this.getBlockingMode()) {
                this.runBlocking(theClient);
                return;
            }

            this.runNonBlocking(theClient);
            if (this.stopServer) {
                logger.log(Level.FINEST, "Closing selector for {0}", this.getName());
                this.selector.close();
            }
        } catch (BindException var26) {
            this.exceptionInRun = var26;
            logger.log(Level.SEVERE, "{0} BindException for Port {1} @ {2} : {3}", new Object[]{this.getName(), this.getPort(), this.getBindAddr().getHostAddress(), var26.getMessage()});
            return;
        } catch (SSLException var27) {
            this.exceptionInRun = var27;
            logger.log(Level.SEVERE, "SSLException {0}", var27);
            logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(var27));
            return;
        } catch (IOException var28) {
            this.exceptionInRun = var28;
            logger.log(Level.SEVERE, "IOError {0}", var28);
            logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(var28));
            return;
        } catch (Exception var29) {
            this.exceptionInRun = var29;
            logger.log(Level.SEVERE, "Error {0}", var29);
            logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(var29));
            return;
        } finally {
            if (this.getBlockingMode()) {
                logger.log(Level.WARNING, "Closing {0}", this.getName());

                try {
                    if (!this.isClosed()) {
                        this.server.close();
                    }
                } catch (Exception var25) {
                    throw new RuntimeException(var25);
                }

                this.server = null;
                this.serverSocketChannel = null;
                this.setServiceState(0);
                logger.log(Level.WARNING, "Closed {0}", this.getName());
                this.processServerHooks(202);
            } else if (!this.getBlockingMode() && this.exceptionInRun != null) {
                logger.log(Level.WARNING, "Closing {0} - Had Error: {1}", new Object[]{this.getName(), this.exceptionInRun});

                try {
                    if (!this.isClosed()) {
                        if (this.serverSocketChannel != null) {
                            this.serverSocketChannel.close();
                        }

                        if (this.server != null) {
                            this.server.close();
                        }
                    }
                } catch (Exception var24) {
                    throw new RuntimeException(var24);
                }

                this.server = null;
                this.serverSocketChannel = null;
                this.setServiceState(0);
                logger.log(Level.WARNING, "Closed {0}", this.getName());
                this.processServerHooks(202);
            }

        }

    }

    public void setMaxConnection(long maxConnection) {
        if (this.getServiceState() == 2) {
            this.suspendMaxConnection = maxConnection;
        } else {
            this.maxConnection = maxConnection;
        }

        logger.log(Level.FINEST, "Set to {0}", maxConnection);
    }

    public long getMaxConnection() {
        return this.maxConnection;
    }

    public long getClientCount() {
        if (this.clientHandlerPool != null) {
            try {
                return (long)this.getClientHandlerPool().getNumActive();
            } catch (Exception var2) {
                return 0L;
            }
        } else {
            return 0L;
        }
    }

    public void setMaxConnectionMsg(String maxConnectionMsg) {
        if (this.getServiceState() == 2) {
            this.suspendMaxConnectionMsg = maxConnectionMsg;
        } else {
            this.maxConnectionMsg = maxConnectionMsg;
        }

        logger.log(Level.FINEST, "Set to {0}", maxConnectionMsg);
    }

    public String getMaxConnectionMsg() {
        return this.maxConnectionMsg;
    }

    public void setBindAddr(String bindAddr) throws UnknownHostException {
        this.ipAddr = InetAddress.getByName(bindAddr);
        logger.log(Level.FINEST, "Set to {0}", bindAddr);
    }

    public InetAddress getBindAddr() {
        if (this.ipAddr == null) {
            try {
                this.ipAddr = InetAddress.getByName("0.0.0.0");
            } catch (Exception var2) {
                logger.log(Level.WARNING, "Unable to create default ip(0.0.0.0) : {0}", var2);
                throw new RuntimeException("Error: Unable to find servers own ip : " + var2);
            }
        }

        return this.ipAddr;
    }

    public void setStoreObjects(Object[] storeObjects) {
        this.storeObjects = storeObjects;
    }

    public Object[] getStoreObjects() {
        return this.storeObjects;
    }

    public void setQSAdminServerPort(int port) {
        this.getQSAdminServer().getServer().setPort(port);
    }

    public int getQSAdminServerPort() {
        return this.getQSAdminServer().getServer().getPort();
    }

    public void setQSAdminServerAuthenticator(String authenticator) {
        this.getQSAdminServer().getServer().setClientAuthenticationHandler(authenticator);
    }

    public String getQSAdminServerAuthenticator() {
        return this.getQSAdminServer().getServer().getAuthenticator();
    }

    public void startQSAdminServer(int port, String authenticator) throws AppException {
        this.getQSAdminServer().setClientAuthenticationHandler(authenticator);
        this.getQSAdminServer().startServer(port);
    }

    public void startQSAdminServer() throws AppException {
        this.getQSAdminServer().startServer();
    }

    public QSAdminServer getQSAdminServer() {
        if (this.adminServer == null) {
            this.adminServer = new QSAdminServer(this);
        }

        return this.adminServer;
    }

    public void setQSAdminServer(QSAdminServer adminServer) {
        if (adminServer == null) {
            this.adminServer = adminServer;
        }

    }

    public boolean isClosed() {
        return this.server == null ? true : this.server.isClosed();
    }

    public Logger getAppLogger() {
        return this.appLogger != null ? this.appLogger : logger;
    }

    public void setAppLogger(Logger appLogger) {
        this.appLogger = appLogger;
    }

    public void setClientObjectHandler(String handler) {
        this.clientObjectHandlerString = handler;
        logger.log(Level.FINEST, "Set to {0}", handler);
    }

    public String getClientObjectHandler() {
        return this.clientObjectHandlerString;
    }

    public void setConsoleLoggingFormatter(String formatter) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        if (formatter != null) {
            this.consoleLoggingformatter = formatter;
            Formatter conformatter = (Formatter)this.getClass(formatter, true).newInstance();
            Logger jdkLogger = Logger.getLogger("");
            Handler[] handlers = jdkLogger.getHandlers();

            for(int index = 0; index < handlers.length; ++index) {
                if (ConsoleHandler.class.isInstance(handlers[index])) {
                    handlers[index].setFormatter(conformatter);
                }
            }

            logger.log(Level.FINEST, "Set to {0}", formatter);
        }
    }

    public String getConsoleLoggingFormatter() {
        return this.consoleLoggingformatter;
    }

    public void setConsoleLoggingToMini() {
        try {
            this.setConsoleLoggingFormatter("org.quickserver.util.logging.MiniFormatter");
        } catch (Exception var2) {
            logger.log(Level.WARNING, "Setting to logging.MiniFormatter : {0}", var2);
        }

    }

    public void setConsoleLoggingToMicro() {
        try {
            this.setConsoleLoggingFormatter("org.quickserver.util.logging.MicroFormatter");
        } catch (Exception var2) {
            logger.log(Level.WARNING, "Setting to MicroFormatter : {0}", var2);
        }

    }

    public void setConsoleLoggingLevel(Level level) {
        Logger rlogger = Logger.getLogger("");
        Handler[] handlers = rlogger.getHandlers();
        boolean isConsole = true;

        try {
            if (System.console() == null) {
                isConsole = false;
            }
        } catch (Throwable var6) {
            ;
        }

        for(int index = 0; index < handlers.length; ++index) {
            if (ConsoleHandler.class.isInstance(handlers[index])) {
                if (!isConsole && level != Level.OFF) {
                    System.out.println("QuickServer: You do not have a console.. so turning console logger off..");
                    level = Level.OFF;
                }

                if (level == Level.OFF) {
                    logger.info("QuickServer: Removing console handler.. ");
                    rlogger.removeHandler(handlers[index]);
                    handlers[index].setLevel(level);
                    handlers[index].close();
                } else {
                    handlers[index].setLevel(level);
                }
            }
        }

        if (level == Level.SEVERE) {
            this.consoleLoggingLevel = "SEVERE";
        } else if (level == Level.WARNING) {
            this.consoleLoggingLevel = "WARNING";
        } else if (level == Level.INFO) {
            this.consoleLoggingLevel = "INFO";
        } else if (level == Level.CONFIG) {
            this.consoleLoggingLevel = "CONFIG";
        } else if (level == Level.FINE) {
            this.consoleLoggingLevel = "FINE";
        } else if (level == Level.FINER) {
            this.consoleLoggingLevel = "FINER";
        } else if (level == Level.FINEST) {
            this.consoleLoggingLevel = "FINEST";
        } else if (level == Level.OFF) {
            this.consoleLoggingLevel = "OFF";
        } else {
            this.consoleLoggingLevel = "UNKNOWN";
        }

        logger.log(Level.FINE, "Set to {0}", level);
    }

    public String getConsoleLoggingLevel() {
        return this.consoleLoggingLevel;
    }

    public void setLoggingLevel(Level level) {
        Logger rlogger = Logger.getLogger("");
        Handler[] handlers = rlogger.getHandlers();

        for(int index = 0; index < handlers.length; ++index) {
            handlers[index].setLevel(level);
        }

        if (level == Level.SEVERE) {
            this.loggingLevel = "SEVERE";
        } else if (level == Level.WARNING) {
            this.loggingLevel = "WARNING";
        } else if (level == Level.INFO) {
            this.loggingLevel = "INFO";
        } else if (level == Level.CONFIG) {
            this.loggingLevel = "CONFIG";
        } else if (level == Level.FINE) {
            this.loggingLevel = "FINE";
        } else if (level == Level.FINER) {
            this.loggingLevel = "FINER";
        } else if (level == Level.FINEST) {
            this.loggingLevel = "FINEST";
        } else if (level == Level.OFF) {
            this.loggingLevel = "OFF";
        } else {
            this.loggingLevel = "UNKNOWN";
        }

        this.consoleLoggingLevel = this.loggingLevel;
        logger.log(Level.FINE, "Set to {0}", level);
    }

    public Throwable getServiceError() {
        return this.serviceError;
    }

    public synchronized boolean initService(Object[] param) {
        this.serviceError = null;

        try {
            this.initServer(param);
            return true;
        } catch (Exception var3) {
            this.serviceError = var3;
            return false;
        }
    }

    public synchronized boolean initService(QuickServerConfig qsConfig) {
        this.serviceError = null;

        try {
            this.initServer(qsConfig);
            return true;
        } catch (Exception var3) {
            this.serviceError = var3;
            return false;
        }
    }

    public boolean startService() {
        this.serviceError = null;
        if (this.getServiceState() == 5) {
            return false;
        } else {
            try {
                this.startServer();
                return true;
            } catch (AppException var2) {
                this.serviceError = var2;
                return false;
            }
        }
    }

    public boolean stopService() {
        this.serviceError = null;
        if (this.getServiceState() == 0) {
            return false;
        } else {
            try {
                this.stopServer();
                this.clearAllPools();
                return true;
            } catch (AppException var2) {
                this.serviceError = var2;
                return false;
            } catch (Exception var3) {
                this.serviceError = var3;
                return false;
            }
        }
    }

    public boolean suspendService() {
        this.serviceError = null;
        if (this.getServiceState() == 5) {
            this.suspendMaxConnection = this.maxConnection;
            this.suspendMaxConnectionMsg = this.maxConnectionMsg;
            this.maxConnection = 0L;
            this.maxConnectionMsg = "Service is suspended.";
            this.setServiceState(2);
            logger.log(Level.INFO, "Service {0} is suspended.", this.getName());
            return true;
        } else {
            return false;
        }
    }

    public boolean resumeService() {
        this.serviceError = null;
        if (this.getServiceState() == 2) {
            this.maxConnection = this.suspendMaxConnection;
            this.maxConnectionMsg = this.suspendMaxConnectionMsg;
            this.setServiceState(5);
            logger.log(Level.INFO, "Service {0} resumed.", this.getName());
            return true;
        } else {
            return false;
        }
    }

    public String info() {
        this.serviceError = null;
        StringBuilder buf = new StringBuilder();
        buf.append(this.getName()).append("\n");
        buf.append(this.getBindAddr().getHostAddress()).append(" ");
        buf.append(this.getPort()).append("\n");
        return buf.toString();
    }

    public synchronized void initServer(Object[] param) throws AppException {
        QuickServerConfig qsConfig = null;

        try {
            qsConfig = ConfigReader.read((String)param[0]);
        } catch (Exception var4) {
            logger.log(Level.SEVERE, "Could not init server from xml file {0} : {1}", new Object[]{(new File((String)param[0])).getAbsolutePath(), var4});
            throw new AppException("Could not init server from xml file", var4);
        }

        this.initServer(qsConfig);
    }

    public synchronized void initServer(QuickServerConfig qsConfig) throws AppException {
        this.setConfig(qsConfig);

        try {
            this.configQuickServer();
            this.loadApplicationClasses();
            InitServerHooks ish = this.getConfig().getInitServerHooks();
            if (ish != null) {
                Iterator iterator = ish.iterator();
                String initServerHookClassName = null;
                Class initServerHookClass = null;
                InitServerHook initServerHook = null;

                while(iterator.hasNext()) {
                    initServerHookClassName = (String)iterator.next();
                    initServerHookClass = this.getClass(initServerHookClassName, true);
                    initServerHook = (InitServerHook)initServerHookClass.newInstance();
                    logger.log(Level.INFO, "Loaded init server hook: {0}", initServerHookClassName);
                    logger.log(Level.FINE, "Init server hook info: {0}", initServerHook.info());
                    initServerHook.handleInit(this);
                }
            }
        } catch (Exception var7) {
            logger.log(Level.SEVERE, "Could not load init server hook: {0}", var7);
            logger.log(Level.WARNING, "StackTrace:\n{0}", MyString.getStackTrace(var7));
            throw new AppException("Could not load init server hook", var7);
        }

        this.setServiceState(1);
        logger.log(Level.FINEST, "\r\n{0}", MyString.getSystemInfo(getVersion()));
    }

    public int getServiceState() {
        return this.serviceState;
    }

    public void setServiceState(int state) {
        this.serviceState = state;
    }

    private void configConsoleLoggingLevel(QuickServer qs, String temp) {
        if (temp.equals("SEVERE")) {
            qs.setConsoleLoggingLevel(Level.SEVERE);
        } else if (temp.equals("WARNING")) {
            qs.setConsoleLoggingLevel(Level.WARNING);
        } else if (temp.equals("INFO")) {
            qs.setConsoleLoggingLevel(Level.INFO);
        } else if (temp.equals("CONFIG")) {
            qs.setConsoleLoggingLevel(Level.CONFIG);
        } else if (temp.equals("FINE")) {
            qs.setConsoleLoggingLevel(Level.FINE);
        } else if (temp.equals("FINER")) {
            qs.setConsoleLoggingLevel(Level.FINER);
        } else if (temp.equals("FINEST")) {
            qs.setConsoleLoggingLevel(Level.FINEST);
        } else if (temp.equals("OFF")) {
            qs.setConsoleLoggingLevel(Level.OFF);
        } else {
            logger.log(Level.WARNING, "unknown level {0}", temp);
        }

    }

    public void configQuickServer(QuickServerConfig config) throws Exception {
        this.setConfig(config);
        this.setBasicConfig(config);
        String temp = config.getConsoleLoggingLevel();
        this.configConsoleLoggingLevel(this, temp);
        temp = null;
        this.setConsoleLoggingFormatter(config.getConsoleLoggingFormatter());
        this.setName(config.getName());
        this.setPort(config.getPort());
        this.setClientEventHandler(config.getClientEventHandler());
        this.setClientCommandHandler(config.getClientCommandHandler());
        if (config.getAuthenticator() != null) {
            this.setAuthenticator(config.getAuthenticator());
        } else if (config.getClientAuthenticationHandler() != null) {
            this.setClientAuthenticationHandler(config.getClientAuthenticationHandler());
        }

        this.setClientObjectHandler(config.getClientObjectHandler());
        this.setClientBinaryHandler(config.getClientBinaryHandler());
        this.setClientWriteHandler(config.getClientWriteHandler());
        this.setClientData(config.getClientData());
        this.setClientExtendedEventHandler(config.getClientExtendedEventHandler());
        this.setDefaultDataMode(config.getDefaultDataMode());
        this.setServerBanner(config.getServerBanner());
        this.setTimeout(config.getTimeout());
        this.setMaxAuthTry(config.getMaxAuthTry());
        this.setMaxAuthTryMsg(config.getMaxAuthTryMsg());
        this.setTimeoutMsg(config.getTimeoutMsg());
        this.setMaxConnection(config.getMaxConnection());
        this.setMaxConnectionMsg(config.getMaxConnectionMsg());
        this.setBindAddr(config.getBindAddr());
        this.setCommunicationLogging(config.getCommunicationLogging());
        this.setSecurityManagerClass(config.getSecurityManagerClass());
        this.setAccessConstraintConfig(config.getAccessConstraintConfig());
        temp = config.getApplicationJarPath();
        if (temp != null) {
            File ajp = new File(temp);
            if (!ajp.isAbsolute()) {
                temp = config.getConfigFile();
                ajp = new File(temp);
                temp = ajp.getParent() + File.separatorChar + config.getApplicationJarPath();
                config.setApplicationJarPath(temp);
                temp = null;
            }

            this.setApplicationJarPath(config.getApplicationJarPath());
            if (config.getQSAdminServerConfig() != null) {
                this.getQSAdminServer().getServer().setApplicationJarPath(config.getApplicationJarPath());
            }
        }

        this.setServerHooks(config.getServerHooks());
        this.setSecure(config.getSecure());
    }

    public void configQuickServer(QSAdminServerConfig config) throws Exception {
        QuickServer qs = this.getQSAdminServer().getServer();
        qs.setBasicConfig(config);
        String temp = this.getConsoleLoggingLevel();
        this.configConsoleLoggingLevel(qs, temp);
        qs.setConsoleLoggingFormatter(this.getConsoleLoggingFormatter());
        qs.setClientEventHandler(config.getClientEventHandler());
        qs.setClientCommandHandler(config.getClientCommandHandler());
        qs.setName(config.getName());
        qs.setPort(config.getPort());
        if (config.getAuthenticator() != null) {
            qs.setAuthenticator(config.getAuthenticator());
        } else if (config.getClientAuthenticationHandler() != null) {
            qs.setClientAuthenticationHandler(config.getClientAuthenticationHandler());
        }

        qs.setClientObjectHandler(config.getClientObjectHandler());
        qs.setClientBinaryHandler(config.getClientBinaryHandler());
        qs.setClientWriteHandler(config.getClientWriteHandler());
        qs.setClientData(config.getClientData());
        qs.setClientExtendedEventHandler(config.getClientExtendedEventHandler());
        qs.setDefaultDataMode(config.getDefaultDataMode());
        qs.setServerBanner(config.getServerBanner());
        qs.setTimeout(config.getTimeout());
        qs.setMaxAuthTry(config.getMaxAuthTry());
        qs.setMaxAuthTryMsg(config.getMaxAuthTryMsg());
        qs.setTimeoutMsg(config.getTimeoutMsg());
        qs.setMaxConnection(config.getMaxConnection());
        qs.setMaxConnectionMsg(config.getMaxConnectionMsg());
        qs.setBindAddr(config.getBindAddr());
        qs.setCommunicationLogging(config.getCommunicationLogging());
        this.getQSAdminServer().setCommandPlugin(config.getCommandPlugin());
        if (config.getCommandShellEnable().equals("true")) {
            this.getQSAdminServer().setShellEnable(true);
        }

        this.getQSAdminServer().setPromptName(config.getCommandShellPromptName());
        qs.setAccessConstraintConfig(config.getAccessConstraintConfig());
        qs.setServerHooks(config.getServerHooks());
        qs.setSecure(config.getSecure());
    }

    public void configQuickServer() throws Exception {
        this.configQuickServer(this.getConfig());
        if (this.getConfig().getQSAdminServerConfig() != null) {
            this.configQuickServer(this.getConfig().getQSAdminServerConfig());
        }

    }

    public static void main(String[] args) {
        try {
            if (args.length >= 1) {
                if (args[0].equals("-about")) {
                    About.main((String[])null);
                } else if (args[0].equals("-load") && args.length >= 2) {
                    QuickServer qs = load(args[1]);
                    if (qs != null) {
                        handleOptions(args, qs);
                    }
                } else {
                    System.out.println(printUsage());
                }
            } else {
                System.out.println(printUsage());
                About.showAbout();
            }
        } catch (Exception var2) {
            var2.printStackTrace();
        }

    }

    public static QuickServer load(String xml) throws AppException {
        QuickServer qs = new QuickServer();
        Object[] config = new Object[]{xml};
        qs.initServer(config);
        qs.startServer();
        if (qs.getConfig().getQSAdminServerConfig() != null) {
            qs.startQSAdminServer();
        }

        return qs;
    }

    private static String printUsage() {
        StringBuilder sb = new StringBuilder();
        sb.append("QuickServer - Java library/framework for creating robust multi-client TCP servers.\n");
        sb.append("Copyright (C) QuickServer.org\n\n");
        sb.append("Usage: QuickServer [-options]\n");
        sb.append("Where options include:\n");
        sb.append("  -about\tOpens About Dialog box\n");
        sb.append("  -load <xml_config_file> [load-options]\tLoads the server from xml file.\n");
        sb.append("  Where load-options include:\n");
        sb.append("     -fullXML2File <file_name>\tDumps the Full XML configuration of the QuickServer loaded.\n");
        return sb.toString();
    }

    private static void handleOptions(String[] args, QuickServer quickserver) {
        if (args.length >= 3) {
            if (args[2].equals("-fullXML2File") && args.length >= 4) {
                File file = new File(args[3]);
                logger.log(Level.INFO, "Writing full xml configuration to file: {0}", file.getAbsolutePath());

                try {
                    TextFile.write(file, quickserver.getConfig().toXML((String)null));
                } catch (Exception var4) {
                    logger.log(Level.WARNING, "Error writing full xml configuration: {0}", var4);
                }
            }

        }
    }

    public void clearAllPools() throws Exception {
        try {
            if (this.pool != null) {
                this.getClientPool().clear();
            }

            if (this.clientHandlerPool != null) {
                this.getClientHandlerPool().clear();
            }

            if (this.getClientDataPool() != null) {
                this.getClientDataPool().clear();
            }

            if (this.getDBPoolUtil() != null) {
                this.getDBPoolUtil().clean();
            }

            if (this.byteBufferPool != null) {
                this.getByteBufferPool().clear();
            }

        } catch (Exception var2) {
            logger.log(Level.WARNING, "Error: {0}", var2);
            throw var2;
        }
    }

    public void closeAllPools() throws Exception {
        if (this.pool != null || this.clientHandlerPool != null || this.getClientDataPool() != null || this.getDBPoolUtil() != null || this.byteBufferPool != null) {
            logger.log(Level.FINE, "Closing pools for {0}", this.getName());

            try {
                if (this.pool != null && PoolHelper.isPoolOpen(this.getClientPool().getObjectPool())) {
                    logger.finer("Closing ClientThread pool.");
                    this.getClientPool().close();
                }

                if (this.clientHandlerPool != null && PoolHelper.isPoolOpen(this.getClientHandlerPool())) {
                    logger.finer("Closing ClientHandler pool.");
                    this.getClientHandlerPool().close();
                }

                if (this.getClientDataPool() != null && PoolHelper.isPoolOpen(this.getClientDataPool())) {
                    logger.finer("Closing ClientData pool.");
                    this.getClientDataPool().close();
                }

                if (this.getDBPoolUtil() != null) {
                    logger.finer("Closing DB pool.");
                    this.getDBPoolUtil().clean();
                }

                if (this.byteBufferPool != null && PoolHelper.isPoolOpen(this.getByteBufferPool())) {
                    logger.finer("Closing ByteBuffer pool.");
                    this.getByteBufferPool().close();
                }

                logger.log(Level.FINE, "Closed pools for {0}", this.getName());
            } catch (Exception var2) {
                logger.log(Level.WARNING, "Error closing pools for {0}: {1}", new Object[]{this.getName(), var2});
                throw var2;
            }
        }
    }

    public void initAllPools() throws Exception {
        logger.fine("Creating pools");
        if (!this.getBlockingMode()) {
            this.makeByteBufferPool(this.getBasicConfig().getObjectPoolConfig().getByteBufferObjectPoolConfig());
        }

        this.makeClientPool(this.getBasicConfig().getObjectPoolConfig().getThreadObjectPoolConfig());
        this.makeClientHandlerPool(this.getBasicConfig().getObjectPoolConfig().getClientHandlerObjectPoolConfig());
        if (this.clientDataClass != null) {
            try {
                this.clientData = (ClientData)this.clientDataClass.newInstance();
                if (PoolableObject.class.isInstance(this.clientData)) {
                    PoolableObject po = (PoolableObject)this.clientData;
                    if (po.isPoolable()) {
                        this.makeClientDataPool(po.getPoolableObjectFactory(), this.getBasicConfig().getObjectPoolConfig().getClientDataObjectPoolConfig());
                    } else {
                        this.clientDataPool = null;
                        logger.fine("ClientData is not poolable!");
                    }
                }
            } catch (Exception var3) {
                logger.log(Level.WARNING, "Error: {0}", var3);
                throw var3;
            }
        }

        try {
            this.makeDBObjectPool();
        } catch (Exception var2) {
            logger.log(Level.WARNING, "Error in makeDBObjectPool() : {0}", var2);
            logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(var2));
            throw var2;
        }

        logger.fine("Created pools");
    }

    public ClientPool getClientPool() {
        if (this.pool == null) {
            throw new IllegalStateException("No ClientPool available yet!");
        } else {
            return this.pool;
        }
    }

    private void makeClientHandlerPool(PoolConfig opConfig) throws Exception {
        logger.finer("Creating ClientHandler pool");
        PoolableObjectFactory factory = new ClientHandlerObjectFactory(this.getBlockingMode());
        this.clientHandlerPool = this.poolManager.makeClientHandlerPool(factory, opConfig);
        this.poolManager.initPool(this.clientHandlerPool, opConfig);
        this.clientHandlerPool = this.makeQSObjectPool(this.clientHandlerPool);
        this.clientIdentifier.setClientHandlerPool((QSObjectPool)this.clientHandlerPool);
    }

    public ObjectPool getClientHandlerPool() {
        if (this.clientHandlerPool == null) {
            throw new IllegalStateException("No ClientHandler Pool available yet!");
        } else {
            return this.clientHandlerPool;
        }
    }

    public void setConfig(QuickServerConfig config) {
        this.config = config;
    }

    public QuickServerConfig getConfig() {
        return this.config;
    }

    private void makeClientDataPool(PoolableObjectFactory factory, PoolConfig opConfig) throws Exception {
        logger.finer("Creating ClientData pool");
        this.clientDataPool = this.poolManager.makeClientDataPool(factory, opConfig);
        this.poolManager.initPool(this.clientDataPool, opConfig);
        this.clientDataPool = this.makeQSObjectPool(this.clientDataPool);
    }

    public ObjectPool getClientDataPool() {
        return this.clientDataPool;
    }

    public DBPoolUtil getDBPoolUtil() {
        return this.dBPoolUtil;
    }

    public void setDBObjectPoolConfig(DBObjectPoolConfig dBObjectPoolConfig) {
        this.getConfig().setDBObjectPoolConfig(dBObjectPoolConfig);
    }

    private void makeDBObjectPool() throws Exception {
        if (this.getConfig().getDBObjectPoolConfig() != null) {
            logger.fine("Creating DBObject Pool");
            Class dbPoolUtilClass = this.getClass(this.getConfig().getDBObjectPoolConfig().getDbPoolUtil(), true);
            this.dBPoolUtil = (DBPoolUtil)dbPoolUtilClass.newInstance();
            this.dBPoolUtil.setDatabaseConnections(this.getConfig().getDBObjectPoolConfig().getDatabaseConnectionSet().iterator());
            this.dBPoolUtil.initPool();
        }

    }

    public ClientHandler findFirstClientById(String id) {
        return this.clientIdentifier.findFirstClientById(id);
    }

    public Iterator findAllClient() {
        return this.clientIdentifier.findAllClient();
    }

    public Iterator findAllClientById(String pattern) {
        return this.clientIdentifier.findAllClientById(pattern);
    }

    public ClientHandler findClientByKey(String key) {
        return this.clientIdentifier.findClientByKey(key);
    }

    public Iterator findAllClientByKey(String pattern) {
        return this.clientIdentifier.findAllClientByKey(pattern);
    }

    public void nextClientIsTrusted() {
        this.setSkipValidation(true);
    }

    private synchronized boolean getSkipValidation() {
        return this.skipValidation;
    }

    private synchronized void setSkipValidation(boolean validation) {
        this.skipValidation = validation;
    }

    public void setCommunicationLogging(boolean communicationLogging) {
        this.communicationLogging = communicationLogging;
    }

    public boolean getCommunicationLogging() {
        return this.communicationLogging;
    }

    public void setSecurityManagerClass(String securityManagerClass) {
        if (securityManagerClass != null) {
            this.securityManagerClass = securityManagerClass;
        }

    }

    public String getSecurityManagerClass() {
        return this.securityManagerClass;
    }

    public SecurityManager getSecurityManager() throws AppException {
        if (this.getSecurityManagerClass() == null) {
            return null;
        } else {
            SecurityManager sm = null;

            try {
                sm = (SecurityManager)this.getClass(this.getSecurityManagerClass(), true).newInstance();
                return sm;
            } catch (ClassNotFoundException var3) {
                throw new AppException(var3.getMessage());
            } catch (InstantiationException var4) {
                throw new AppException(var4.getMessage());
            } catch (IllegalAccessException var5) {
                throw new AppException(var5.getMessage());
            }
        }
    }

    public void setAccessConstraintConfig(AccessConstraintConfig accessConstraintConfig) {
        this.accessConstraintConfig = accessConstraintConfig;
    }

    public AccessConstraintConfig getAccessConstraintConfig() {
        return this.accessConstraintConfig;
    }

    public void setClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
        Thread.currentThread().setContextClassLoader(classLoader);
    }

    public ClassLoader getClassLoader() {
        return this.classLoader;
    }

    public Class getClass(String name, boolean reload) throws ClassNotFoundException {
        if (name == null) {
            throw new IllegalArgumentException("Class name can't be null!");
        } else {
            logger.log(Level.FINEST, "Class: {0}, reload: {1}", new Object[]{name, reload});
            if (reload && this.classLoader != null) {
                return this.classLoader.loadClass(name);
            } else if (reload && this.classLoader == null && this.getClass().getClassLoader() != null) {
                return this.getClass().getClassLoader().loadClass(name);
            } else {
                return !reload && this.classLoader != null ? Class.forName(name, true, this.classLoader) : Class.forName(name, true, this.getClass().getClassLoader());
            }
        }
    }

    protected void setApplicationJarPath(String applicationJarPath) {
        this.applicationJarPath = applicationJarPath;
    }

    public String getApplicationJarPath() {
        return this.applicationJarPath;
    }

    public void setServerHooks(ServerHooks serverHooks) {
        this.serverHooks = serverHooks;
    }

    public ServerHooks getServerHooks() {
        if (this.serverHooks == null) {
            this.serverHooks = new ServerHooks();
        }

        return this.serverHooks;
    }

    private void loadServerHooksClasses() {
        if (this.getServerHooks() != null) {
            this.listOfServerHooks = new ArrayList();
            ServerHook serverHook = null;
            String serverHookClassName = null;
            Class serverHookClass = null;
            serverHook = new GhostSocketReaper();
            serverHook.initHook(this);
            this.listOfServerHooks.add(serverHook);
            this.ghostSocketReaper = (GhostSocketReaper)serverHook;
            Iterator iterator = this.getServerHooks().iterator();

            while(iterator.hasNext()) {
                serverHookClassName = (String)iterator.next();

                try {
                    serverHookClass = this.getClass(serverHookClassName, true);
                    serverHook = (ServerHook)serverHookClass.newInstance();
                    serverHook.initHook(this);
                    this.listOfServerHooks.add(serverHook);
                    logger.log(Level.INFO, "Loaded server hook: {0}", serverHookClassName);
                    logger.log(Level.FINE, "Server hook info: {0}", serverHook.info());
                } catch (Exception var6) {
                    logger.log(Level.WARNING, "Could not load server hook [{0}]: {1}", new Object[]{serverHookClassName, var6});
                    logger.log(Level.FINE, "StackTrace:\n{0}", MyString.getStackTrace(var6));
                }
            }

        }
    }

    protected void processServerHooks(int event) {
        if (this.listOfServerHooks == null) {
            logger.warning("listOfServerHooks was null!");
        } else {
            ServerHook serverHook = null;
            boolean result = false;
            Iterator iterator = this.listOfServerHooks.iterator();
            String hooktype = "UNKNOWN";
            switch(event) {
            case 100:
                hooktype = "PRE_STARTUP";
                break;
            case 101:
                hooktype = "POST_STARTUP";
                break;
            case 201:
                hooktype = "PRE_SHUTDOWN";
                break;
            case 202:
                hooktype = "POST_SHUTDOWN";
            }

            for(; iterator.hasNext(); logger.log(Level.FINE, "Invoked {0} hook [{1}] was: {2}", new Object[]{hooktype, serverHook.getClass().getName(), result})) {
                serverHook = (ServerHook)iterator.next();

                try {
                    result = serverHook.handleEvent(event);
                } catch (Exception var7) {
                    result = false;
                    logger.log(Level.WARNING, "Error invoking {0} hook [{1}]: {2}", new Object[]{hooktype, serverHook.getClass().getName(), var7.getMessage()});
                }
            }

        }
    }

    public Object clone() {
        Object object = null;

        try {
            object = super.clone();
            QuickServer _qs = (QuickServer)object;
            _qs.setQSAdminServer(new QSAdminServer(_qs));
        } catch (CloneNotSupportedException var3) {
            logger.log(Level.WARNING, "Error cloning : {0}", var3);
        }

        return object;
    }

    public void setSecure(Secure secure) {
        this.secure = secure;
    }

    public Secure getSecure() {
        if (this.secure == null) {
            this.secure = new Secure();
        }

        return this.secure;
    }

    public boolean isRunningSecure() {
        return this.runningSecure;
    }

    public void setRunningSecure(boolean runningSecure) {
        this.runningSecure = runningSecure;
    }

    private File makeAbsoluteToConfig(String fileName) {
        Assertion.affirm(fileName != null, "FileName can't be null");
        return ConfigReader.makeAbsoluteToConfig(fileName, this.getConfig());
    }

    protected void makeServerSocket() throws BindException, IOException {
        this.server = null;
        logger.log(Level.FINEST, "Binding {0} to IP: {1}", new Object[]{this.getName(), this.getBindAddr()});
        InetSocketAddress bindAddress = new InetSocketAddress(this.getBindAddr(), this.getPort());

        try {
            NetworkInterface ni = NetworkInterface.getByInetAddress(this.getBindAddr());
            if (ni != null) {
                logger.fine("NetworkInterface: " + ni);
            }
        } catch (Exception var8) {
            ;
        } catch (Error var9) {
            ;
        }

        if (!this.getSecure().isEnable()) {
            logger.log(Level.FINE, "Making a normal ServerSocket for {0}", this.getName());
            this.setRunningSecure(false);
            if (!this.getBlockingMode()) {
                this.serverSocketChannel = ServerSocketChannel.open();
                this.server = this.serverSocketChannel.socket();
                this.server.bind(bindAddress, this.getBasicConfig().getAdvancedSettings().getBacklog());
            } else {
                this.server = new ServerSocket(this.getPort(), this.getBasicConfig().getAdvancedSettings().getBacklog(), this.getBindAddr());
            }
        } else {
            try {
                logger.log(Level.FINE, "Making a secure ServerSocket for {0}", this.getName());
                this.getSSLContext();
                this.setRunningSecure(true);
                if (!this.getBlockingMode()) {
                    logger.log(Level.FINE, "Making a secure ServerSocketChannel for {0}", this.getName());
                    this.serverSocketChannel = ServerSocketChannel.open();
                    this.server = this.serverSocketChannel.socket();
                    this.server.bind(bindAddress, this.getBasicConfig().getAdvancedSettings().getBacklog());
                } else {
                    ServerSocketFactory ssf = this.getSSLContext().getServerSocketFactory();
                    SSLServerSocket serversocket = (SSLServerSocket)ssf.createServerSocket(this.getPort(), this.getBasicConfig().getAdvancedSettings().getBacklog(), this.getBindAddr());
                    serversocket.setNeedClientAuth(this.secure.isClientAuthEnable());
                    this.setRunningSecure(true);
                    this.secureStoreManager.logSSLServerSocketInfo(serversocket);
                    this.server = serversocket;
                    this.serverSocketChannel = this.server.getChannel();
                    if (this.serverSocketChannel == null && !this.getBlockingMode()) {
                        logger.warning("Secure Server does not support Channel! So will run in blocking mode.");
                        this.blockingMode = false;
                    }
                }
            } catch (NoSuchAlgorithmException var6) {
                logger.log(Level.WARNING, "NoSuchAlgorithmException : {0}", var6);
                throw new IOException("Error creating secure socket : " + var6.getMessage());
            } catch (KeyManagementException var7) {
                logger.log(Level.WARNING, "KeyManagementException : {0}", var7);
                throw new IOException("Error creating secure socket : " + var7.getMessage());
            }
        }

        this.server.setReuseAddress(true);
        int connectionTime = 0;
        int latency = 0;
        int bandwidth = 0;
        connectionTime = this.getBasicConfig().getAdvancedSettings().getPerformancePreferencesConnectionTime();
        latency = this.getBasicConfig().getAdvancedSettings().getPerformancePreferencesLatency();
        bandwidth = this.getBasicConfig().getAdvancedSettings().getPerformancePreferencesBandwidth();
        logger.log(Level.FINE, "getPerformancePreferencesConnectionTime : {0}", connectionTime);
        logger.log(Level.FINE, "getPerformancePreferencesLatency : {0}", latency);
        logger.log(Level.FINE, "getPerformancePreferencesBandwidth : {0}", bandwidth);
        this.server.setPerformancePreferences(connectionTime, latency, bandwidth);
        int clientSocketReceiveBufferSize = this.getBasicConfig().getAdvancedSettings().getClientSocketReceiveBufferSize();
        if (clientSocketReceiveBufferSize > 0) {
            logger.log(Level.FINE, "clientSocketReceiveBufferSize: {0}", clientSocketReceiveBufferSize);
            this.server.setReceiveBufferSize(clientSocketReceiveBufferSize);
        }

        if (!this.getBlockingMode()) {
            logger.log(Level.FINE, "Server Mode {0} - Non Blocking", this.getName());
            if (this.selector != null && this.selector.isOpen()) {
                logger.log(Level.FINEST, "Reusing selector: {0}", this.selector);
            } else {
                logger.finest("Opening new selector");
                this.selector = Selector.open();
            }

            this.serverSocketChannel.configureBlocking(false);
            this.serverSocketChannel.register(this.selector, 16);
            this.selector.wakeup();
        } else {
            logger.log(Level.FINE, "Server Mode {0} - Blocking", this.getName());
        }

    }

    public void setBasicConfig(BasicServerConfig basicConfig) throws Exception {
        Assertion.affirm(basicConfig != null, "BasicServerConfig can't be null");
        this.basicConfig = basicConfig;
    }

    public BasicServerConfig getBasicConfig() {
        return this.basicConfig;
    }

    public void loadSSLContext() throws IOException {
        if (!this.getSecure().isLoad()) {
            throw new IllegalStateException("Secure setting is not yet enabled for loading!");
        } else {
            logger.info("Loading Secure Context..");
            this.km = null;
            this.tm = null;

            try {
                String ssManager = "org.quickserver.security.SecureStoreManager";
                if (this.getSecure().getSecureStore() != null) {
                    ssManager = this.getSecure().getSecureStore().getSecureStoreManager();
                }

                Class secureStoreManagerClass = this.getClass(ssManager, true);
                this.secureStoreManager = (SecureStoreManager)secureStoreManagerClass.newInstance();
                this.km = this.secureStoreManager.loadKeyManagers(this.getConfig());
                logger.fine("KeyManager got");
                this.tm = this.secureStoreManager.loadTrustManagers(this.getConfig());
                logger.fine("TrustManager got");
                this.sslc = this.secureStoreManager.getSSLContext(this.getConfig().getSecure().getProtocol());
                this.sslc.init(this.km, this.tm, (SecureRandom)null);
                logger.fine("SSLContext loaded");
            } catch (KeyStoreException var3) {
                logger.warning("KeyStoreException : " + var3);
                throw new IOException("Error creating secure socket : " + var3.getMessage());
            } catch (NoSuchAlgorithmException var4) {
                logger.warning("NoSuchAlgorithmException : " + var4);
                throw new IOException("Error creating secure socket : " + var4.getMessage());
            } catch (NoSuchProviderException var5) {
                logger.warning("NoSuchProviderException : " + var5);
                throw new IOException("Error creating secure socket : " + var5.getMessage());
            } catch (UnrecoverableKeyException var6) {
                logger.warning("UnrecoverableKeyException : " + var6);
                throw new IOException("Error creating secure socket : " + var6.getMessage());
            } catch (CertificateException var7) {
                logger.warning("CertificateException : " + var7);
                throw new IOException("Error creating secure socket : " + var7.getMessage());
            } catch (KeyManagementException var8) {
                logger.warning("KeyManagementException : " + var8);
                throw new IOException("Error creating secure socket : " + var8.getMessage());
            } catch (GeneralSecurityException var9) {
                logger.warning("GeneralSecurityException : " + var9);
                throw new IOException("Error creating secure socket : " + var9.getMessage());
            } catch (ClassNotFoundException var10) {
                logger.warning("ClassNotFoundException : " + var10);
                throw new IOException("Error creating secure socket : " + var10.getMessage());
            } catch (InstantiationException var11) {
                logger.warning("InstantiationException : " + var11);
                throw new IOException("Error creating secure socket : " + var11.getMessage());
            } catch (IllegalAccessException var12) {
                logger.warning("IllegalAccessException : " + var12);
                throw new IOException("Error creating secure socket : " + var12.getMessage());
            }
        }
    }

    public SSLContext getSSLContext() throws IOException, NoSuchAlgorithmException, KeyManagementException {
        return this.getSSLContext((String)null);
    }

    public SSLContext getSSLContext(String protocol) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        if (this.sslc == null) {
            this.loadSSLContext();
        }

        if (protocol != null && this.secureStoreManager != null) {
            SSLContext _sslc = this.secureStoreManager.getSSLContext(protocol);
            _sslc.init(this.km, this.tm, (SecureRandom)null);
            return _sslc;
        } else {
            return this.sslc;
        }
    }

    public SSLSocketFactory getSSLSocketFactory() throws IOException, NoSuchAlgorithmException, KeyManagementException {
        if (this.sslc == null) {
            this.loadSSLContext();
        }

        return this.secureStoreManager.getSocketFactory(this.getSSLContext());
    }

    public SSLSocketFactory getSSLSocketFactory(String protocol) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        if (this.sslc == null) {
            this.loadSSLContext();
        }

        return this.secureStoreManager.getSocketFactory(this.getSSLContext(protocol));
    }

    public void setClientBinaryHandler(String handler) {
        this.clientBinaryHandlerString = handler;
        logger.finest("Set to " + handler);
    }

    public String getClientBinaryHandler() {
        return this.clientBinaryHandlerString;
    }

    public void setSelector(Selector selector) {
        this.selector = selector;
    }

    public Selector getSelector() {
        return this.selector;
    }

    private void runBlocking(TheClient theClient) throws Exception {
        Socket client = null;
        ClientHandler _chPolled = null;
        int linger = this.getBasicConfig().getAdvancedSettings().getSocketLinger();
        int socketTrafficClass = 0;
        if (this.getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass() != null) {
            socketTrafficClass = Integer.parseInt(this.getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass());
        }

        while(true) {
            do {
                client = this.server.accept();
                if (linger < 0) {
                    client.setSoLinger(false, 0);
                } else {
                    client.setSoLinger(true, linger);
                }

                client.setTcpNoDelay(this.getBasicConfig().getAdvancedSettings().getClientSocketTcpNoDelay());
                if (this.getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass() != null) {
                    client.setTrafficClass(socketTrafficClass);
                }

                if (this.getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize() != 0) {
                    client.setSendBufferSize(this.getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize());
                }

                if (this.stopServer) {
                    try {
                        client.close();
                    } catch (Exception var7) {
                        ;
                    }

                    return;
                }
            } while(!this.checkAccessConstraint(client));

            if (!this.getSkipValidation() && this.maxConnection != -1L && (long)this.getClientHandlerPool().getNumActive() >= this.maxConnection) {
                theClient.setClientEvent(ClientEvent.MAX_CON_BLOCKING);
            } else {
                theClient.setClientEvent(ClientEvent.RUN_BLOCKING);
            }

            theClient.setTrusted(this.getSkipValidation());
            theClient.setSocket(client);
            theClient.setSocketChannel(client.getChannel());
            if (this.clientDataClass != null) {
                if (this.getClientDataPool() == null) {
                    this.clientData = (ClientData)this.clientDataClass.newInstance();
                } else {
                    this.clientData = (ClientData)this.getClientDataPool().borrowObject();
                }

                theClient.setClientData(this.clientData);
            }

            try {
                _chPolled = (ClientHandler)this.getClientHandlerPool().borrowObject();
                _chPolled.handleClient(theClient);
            } catch (NoSuchElementException var9) {
                logger.warning("Could not borrow ClientHandler from pool. Error: " + var9);
                logger.warning("Closing Socket [" + client + "] since no ClientHandler available.");
                client.close();
            }

            if (_chPolled != null) {
                try {
                    this.getClientPool().addClient(_chPolled, true);
                } catch (NoSuchElementException var8) {
                    logger.warning("Could not borrow Thread from pool. Error: " + var8);
                }

                _chPolled = null;
            }

            client = null;
            this.setSkipValidation(false);
        }
    }

    private void runNonBlocking(TheClient theClient) throws Exception {
        int selectCount = 0;
        Iterator iterator = null;
        SelectionKey key = null;
        ServerSocketChannel serverChannel = null;
        SocketChannel socketChannel = null;
        Socket client = null;
        ClientHandler _chPolled = null;
        boolean stopServerProcessed = false;
        int linger = this.getBasicConfig().getAdvancedSettings().getSocketLinger();
        this.registerChannelRequestMap = new HashMap();
        int socketTrafficClass = 0;
        if (this.getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass() != null) {
            socketTrafficClass = Integer.parseInt(this.getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass());
        }

        while(true) {
            selectCount = this.selector.select(500L);
            synchronized(this.registerChannelRequestMap) {
                if (this.registerChannelRequestMap.size() > 0) {
                	 RegisterChannelRequest req = null;
                    Object hashkey = null;
                    iterator = this.registerChannelRequestMap.keySet().iterator();

                    while(iterator.hasNext()) {
                        hashkey = iterator.next();
                        req = (RegisterChannelRequest)this.registerChannelRequestMap.get(hashkey);
                        req.register(this.getSelector());
                    }

                    iterator = null;
                    this.registerChannelRequestMap.clear();
                }
            }

            if (this.stopServer && !stopServerProcessed) {
                logger.warning("Closing " + this.getName());
                this.serverSocketChannel.close();
                stopServerProcessed = true;
                this.server = null;
                this.serverSocketChannel = null;
                this.setServiceState(0);
                logger.warning("Closed " + this.getName());
                this.processServerHooks(202);
            }

            if (!this.stopServer && stopServerProcessed) {
                logger.finest("Server must have re-started.. will break");
                break;
            }

            if (selectCount == 0 && stopServerProcessed) {
                Set keyset = this.selector.keys();
                if (keyset.isEmpty() && this.getClientCount() <= 0L) {
                    break;
                }
            } else if (selectCount != 0) {
                iterator = this.selector.selectedKeys().iterator();

                while(true) {
                    while(iterator.hasNext()) {
                        key = (SelectionKey)iterator.next();
                        if (!key.isValid()) {
                            iterator.remove();
                        } else {
                            if (key.isAcceptable() && !this.stopServer) {
                                logger.finest("Key is Acceptable");
                                serverChannel = (ServerSocketChannel)key.channel();
                                socketChannel = serverChannel.accept();
                                if (socketChannel == null) {
                                    iterator.remove();
                                    continue;
                                }

                                client = socketChannel.socket();
                                if (linger < 0) {
                                    client.setSoLinger(false, 0);
                                } else {
                                    client.setSoLinger(true, linger);
                                }

                                client.setTcpNoDelay(this.getBasicConfig().getAdvancedSettings().getClientSocketTcpNoDelay());
                                if (this.getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass() != null) {
                                    client.setTrafficClass(socketTrafficClass);
                                }

                                if (this.getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize() != 0) {
                                    client.setSendBufferSize(this.getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize());
                                }

                                if (!this.checkAccessConstraint(client)) {
                                    iterator.remove();
                                    continue;
                                }

                                socketChannel.configureBlocking(false);
                                theClient.setTrusted(this.getSkipValidation());
                                theClient.setSocket(socketChannel.socket());
                                theClient.setSocketChannel(socketChannel);
                                if (this.clientDataClass != null) {
                                    if (this.getClientDataPool() == null) {
                                        this.clientData = (ClientData)this.clientDataClass.newInstance();
                                    } else {
                                        this.clientData = (ClientData)this.getClientDataPool().borrowObject();
                                    }

                                    theClient.setClientData(this.clientData);
                                }

                                if (!this.getSkipValidation() && this.maxConnection != -1L && (long)this.getClientHandlerPool().getNumActive() >= this.maxConnection) {
                                    theClient.setClientEvent(ClientEvent.MAX_CON);
                                } else {
                                    theClient.setClientEvent(ClientEvent.ACCEPT);
                                }

                                try {
                                    _chPolled = (ClientHandler)this.getClientHandlerPool().borrowObject();
                                    logger.finest("Asking " + _chPolled.getName() + " to handle.");
                                    _chPolled.handleClient(theClient);
                                } catch (NoSuchElementException var16) {
                                    logger.warning("Could not borrow ClientHandler Object from pool. Error: " + var16);
                                    logger.warning("Closing SocketChannel [" + serverChannel.socket() + "] since no ClientHandler available.");
                                    socketChannel.close();
                                }

                                if (_chPolled != null) {
                                    try {
                                        this.getClientPool().addClient(_chPolled, true);
                                    } catch (NoSuchElementException var15) {
                                        logger.warning("Could not borrow Thread from pool. Error: " + var15);
                                    }

                                    _chPolled = null;
                                }

                                socketChannel = null;
                                client = null;
                                this.setSkipValidation(false);
                            } else if (key.isValid() && key.isReadable()) {
                            	boolean addedEvent = false;
                                    ClientHandler _ch = null;
                                    try {
                                        _ch = (ClientHandler)key.attachment();
                                        logger.finest("Key is Readable, removing OP_READ from interestOps for " + _ch.getName());
                                        key.interestOps(key.interestOps() & -2);
                                        _ch.addEvent(ClientEvent.READ);
                                        addedEvent = true;
                                        this.getClientPool().addClient(_ch);
                                    } catch (CancelledKeyException var20) {
                                        logger.fine("Ignored Error - Key was Cancelled: " + var20);
                                    } catch (NoSuchElementException var21) {
                                        logger.finest("NoSuchElementException: " + var21);
                                        if (addedEvent) {
                                            _ch.removeEvent(ClientEvent.READ);
                                        }
                                        continue;
                                    }

                                    _ch = null;
                                } else if (key.isValid() && key.isWritable()) {
                                    if (!this.getClientPool().shouldNioWriteHappen()) {
                                        continue;
                                    }
                                    boolean addedEvent = false;
                                    ClientHandler _ch = null;
                                    try {
                                        _ch = (ClientHandler)key.attachment();
                                        logger.finest("Key is Writable, removing OP_WRITE from interestOps for " + _ch.getName());
                                        key.interestOps(key.interestOps() & -5);
                                        _ch.addEvent(ClientEvent.WRITE);
                                        addedEvent = true;
                                        this.getClientPool().addClient(_ch);
                                    } catch (CancelledKeyException var18) {
                                        logger.fine("Ignored Error - Key was Cancelled: " + var18);
                                    } catch (NoSuchElementException var19) {
                                        logger.finest("NoSuchElementException: " + var19);
                                        if (addedEvent) {
                                            _ch.removeEvent(ClientEvent.WRITE);
                                        }
                                        continue;
                                    }

                                    _ch = null;
                                } else if (this.stopServer && key.isAcceptable()) {
                                    this.setSkipValidation(false);
                                } else {
                                    logger.warning("Unknown key got in SelectionKey: " + key);
                                }
                            }

                            iterator.remove();
                            Thread.yield();
                        }
                    }
            }
                    iterator = null;
                }
            }

    private boolean checkAccessConstraint(Socket socket) {
        try {
            if (this.getAccessConstraintConfig() != null) {
                this.getAccessConstraintConfig().checkAccept(socket);
            }

            return true;
        } catch (SecurityException var3) {
            logger.warning("SecurityException occurred accepting connection : " + var3.getMessage());
            return false;
        }
    }

    public boolean registerChannel(SocketChannel channel, int ops, Object att) throws IOException, ClosedChannelException {
        if (this.getSelector() == null) {
            throw new IllegalStateException("Selector is not open!");
        } else if (channel == null) {
            throw new IllegalArgumentException("Can't register a null channel!");
        } else if (!channel.isConnected()) {
            throw new ClosedChannelException();
        } else {
            RegisterChannelRequest req = new RegisterChannelRequest(channel, ops, att);
            RegisterChannelRequest reqOld = null;
            Map var6 = this.registerChannelRequestMap;
            synchronized(this.registerChannelRequestMap) {
                reqOld = (RegisterChannelRequest)this.registerChannelRequestMap.get(channel);
                if (reqOld == null) {
                    this.registerChannelRequestMap.put(channel, req);
                    this.getSelector().wakeup();
                    return true;
                } else if (!reqOld.equals(req)) {
                    reqOld.setOps(reqOld.getOps() | req.getOps());
                    reqOld.setAtt(req.getAtt());
                    return true;
                } else {
                    return false;
                }
            }
        }
    }

    private void makeByteBufferPool(PoolConfig opConfig) {
        logger.finer("Creating ByteBufferPool pool");
        int bufferSize = this.getBasicConfig().getAdvancedSettings().getByteBufferSize();
        boolean useDirectByteBuffer = this.getBasicConfig().getAdvancedSettings().getUseDirectByteBuffer();
        PoolableObjectFactory factory = new ByteBufferObjectFactory(bufferSize, useDirectByteBuffer);
        this.byteBufferPool = this.poolManager.makeByteBufferPool(factory, opConfig);
        this.poolManager.initPool(this.byteBufferPool, opConfig);
    }

    public ObjectPool getByteBufferPool() {
        return this.byteBufferPool;
    }

    private void makeClientPool(PoolConfig opConfig) throws Exception {
        logger.finer("Creating ClientThread pool");
        ThreadObjectFactory factory = new ThreadObjectFactory();
        ObjectPool objectPool = this.poolManager.makeClientPool(factory, opConfig);
        this.pool = new ClientPool(this.makeQSObjectPool(objectPool), opConfig);
        factory.setClientPool(this.pool);
        this.pool.setMaxThreadsForNioWrite(this.getBasicConfig().getAdvancedSettings().getMaxThreadsForNioWrite());
        this.poolManager.initPool(objectPool, opConfig);
    }

    public void setClientWriteHandler(String handler) {
        this.clientWriteHandlerString = handler;
        logger.finest("Set to " + handler);
    }

    public String getClientWriteHandler() {
        return this.clientWriteHandlerString;
    }

    public Date getLastStartTime() {
        return this.lastStartTime;
    }

    public static void setDebugNonBlockingMode(boolean flag) {
        ByteBufferOutputStream.setDebug(flag);
        ByteBufferInputStream.setDebug(flag);
    }

    public ClientIdentifier getClientIdentifier() {
        return this.clientIdentifier;
    }

    private QSObjectPool makeQSObjectPool(ObjectPool objectPool) throws Exception {
        return this.qsObjectPoolMaker.getQSObjectPool(objectPool);
    }

    public boolean getBlockingMode() {
        return this.blockingMode;
    }

    protected void loadBusinessLogic() throws Exception {
        if (this.clientCommandHandlerString == null && this.clientEventHandlerString == null) {
            logger.severe("ClientCommandHandler AND ClientEventHandler was not set.");
            throw new AppException("ClientCommandHandler AND ClientEventHandler was not set.");
        } else {
            this.clientCommandHandler = null;
            if (this.clientCommandHandlerString != null) {
                logger.finest("Loading ClientCommandHandler class..");
                Class clientCommandHandlerClass = this.getClass(this.clientCommandHandlerString, true);
                this.clientCommandHandler = (ClientCommandHandler)clientCommandHandlerClass.newInstance();
            }

            boolean setClientCommandHandlerLookup = false;
            this.clientEventHandler = null;
            if (this.clientEventHandlerString == null) {
                this.clientEventHandlerString = "org.quickserver.net.server.impl.DefaultClientEventHandler";
                setClientCommandHandlerLookup = true;
            }

            logger.finest("Loading ClientEventHandler class..");
            if (this.clientEventHandlerString.equals(this.clientCommandHandlerString) && ClientEventHandler.class.isInstance(this.clientCommandHandler)) {
                this.clientEventHandler = (ClientEventHandler)this.clientCommandHandler;
            } else {
                this.clientEventHandler = (ClientEventHandler)this.getClass(this.clientEventHandlerString, true).newInstance();
                if (setClientCommandHandlerLookup) {
                    ((DefaultClientEventHandler)this.clientEventHandler).setClientCommandHandler(this.clientCommandHandler);
                }
            }

            this.clientExtendedEventHandler = null;
            Class authenticatorClass;
            if (this.clientExtendedEventHandlerString != null) {
                logger.finest("Loading ClientExtendedEventHandler class..");
                if (this.clientExtendedEventHandlerString.equals(this.clientCommandHandlerString) && ClientExtendedEventHandler.class.isInstance(this.clientCommandHandler)) {
                    this.clientExtendedEventHandler = (ClientExtendedEventHandler)this.clientCommandHandler;
                } else if (this.clientExtendedEventHandlerString.equals(this.clientEventHandlerString) && ClientExtendedEventHandler.class.isInstance(this.clientEventHandler)) {
                    this.clientExtendedEventHandler = (ClientExtendedEventHandler)this.clientEventHandler;
                } else {
                    authenticatorClass = this.getClass(this.clientExtendedEventHandlerString, true);
                    this.clientExtendedEventHandler = (ClientExtendedEventHandler)authenticatorClass.newInstance();
                }
            }

            this.clientObjectHandler = null;
            if (this.clientObjectHandlerString != null) {
                logger.finest("Loading ClientObjectHandler class..");
                if (this.clientObjectHandlerString.equals(this.clientCommandHandlerString) && ClientObjectHandler.class.isInstance(this.clientCommandHandler)) {
                    this.clientObjectHandler = (ClientObjectHandler)this.clientCommandHandler;
                } else if (this.clientObjectHandlerString.equals(this.clientEventHandlerString) && ClientObjectHandler.class.isInstance(this.clientEventHandler)) {
                    this.clientObjectHandler = (ClientObjectHandler)this.clientEventHandler;
                } else if (this.clientObjectHandlerString.equals(this.clientExtendedEventHandlerString) && ClientObjectHandler.class.isInstance(this.clientExtendedEventHandler)) {
                    this.clientObjectHandler = (ClientObjectHandler)this.clientExtendedEventHandler;
                } else {
                    this.clientObjectHandler = (ClientObjectHandler)this.getClass(this.clientObjectHandlerString, true).newInstance();
                }
            }

            this.clientBinaryHandler = null;
            if (this.clientBinaryHandlerString != null) {
                logger.finest("Loading ClientBinaryHandler class..");
                if (this.clientBinaryHandlerString.equals(this.clientCommandHandlerString) && ClientBinaryHandler.class.isInstance(this.clientCommandHandler)) {
                    this.clientBinaryHandler = (ClientBinaryHandler)this.clientCommandHandler;
                } else if (this.clientBinaryHandlerString.equals(this.clientEventHandlerString) && ClientBinaryHandler.class.isInstance(this.clientEventHandler)) {
                    this.clientBinaryHandler = (ClientBinaryHandler)this.clientEventHandler;
                } else if (this.clientBinaryHandlerString.equals(this.clientExtendedEventHandlerString) && ClientBinaryHandler.class.isInstance(this.clientExtendedEventHandler)) {
                    this.clientBinaryHandler = (ClientBinaryHandler)this.clientExtendedEventHandler;
                } else if (this.clientBinaryHandlerString.equals(this.clientObjectHandlerString) && ClientBinaryHandler.class.isInstance(this.clientObjectHandler)) {
                    this.clientBinaryHandler = (ClientBinaryHandler)this.clientObjectHandler;
                } else {
                    this.clientBinaryHandler = (ClientBinaryHandler)this.getClass(this.clientBinaryHandlerString, true).newInstance();
                }
            }

            this.clientWriteHandler = null;
            if (this.clientWriteHandlerString != null) {
                logger.finest("Loading ClientWriteHandler class..");
                if (this.clientWriteHandlerString.equals(this.clientCommandHandlerString) && ClientWriteHandler.class.isInstance(this.clientCommandHandler)) {
                    this.clientWriteHandler = (ClientWriteHandler)this.clientCommandHandler;
                } else if (this.clientWriteHandlerString.equals(this.clientEventHandlerString) && ClientWriteHandler.class.isInstance(this.clientEventHandler)) {
                    this.clientWriteHandler = (ClientWriteHandler)this.clientEventHandler;
                } else if (this.clientWriteHandlerString.equals(this.clientExtendedEventHandlerString) && ClientWriteHandler.class.isInstance(this.clientExtendedEventHandler)) {
                    this.clientWriteHandler = (ClientWriteHandler)this.clientExtendedEventHandler;
                } else if (this.clientWriteHandlerString.equals(this.clientObjectHandlerString) && ClientWriteHandler.class.isInstance(this.clientObjectHandler)) {
                    this.clientWriteHandler = (ClientWriteHandler)this.clientObjectHandler;
                } else if (this.clientWriteHandlerString.equals(this.clientBinaryHandlerString) && ClientWriteHandler.class.isInstance(this.clientBinaryHandler)) {
                    this.clientWriteHandler = (ClientWriteHandler)this.clientBinaryHandler;
                } else {
                    this.clientWriteHandler = (ClientWriteHandler)this.getClass(this.clientWriteHandlerString, true).newInstance();
                }
            }

            authenticatorClass = null;
            if (this.clientAuthenticationHandlerString != null) {
                logger.finest("Loading ClientAuthenticationHandler class..");
                authenticatorClass = this.getClass(this.clientAuthenticationHandlerString, true);
            }

            if (authenticatorClass != null) {
                Object obj = authenticatorClass.newInstance();
                if (ClientAuthenticationHandler.class.isInstance(obj)) {
                    this.clientAuthenticationHandler = (ClientAuthenticationHandler)obj;
                } else {
                    this.authenticator = (Authenticator)obj;
                }
            }

            this.clientDataClass = null;
            if (this.clientDataString != null) {
                logger.finest("Loading ClientData class..");
                this.clientDataClass = this.getClass(this.clientDataString, true);
            }

            Assertion.affirm(this.clientEventHandler != null, "ClientEventHandler was not loaded!");
        }
    }

    public void setClientEventHandler(String handler) {
        this.clientEventHandlerString = handler;
        logger.finest("Set to " + handler);
    }

    public String getClientEventHandler() {
        return this.clientEventHandlerString;
    }

    public void setDefaultDataMode(DataMode dataMode, DataType dataType) throws IOException {
        if (dataType == DataType.IN) {
            this.defaultDataModeIN = dataMode;
        }

        if (dataType == DataType.OUT) {
            this.defaultDataModeOUT = dataMode;
        }

    }

    public void setDefaultDataMode(DefaultDataMode defaultDataMode) throws IOException {
        this.defaultDataModeIN = defaultDataMode.getDataMode(DataType.IN);
        this.defaultDataModeOUT = defaultDataMode.getDataMode(DataType.OUT);
    }

    public DataMode getDefaultDataMode(DataType dataType) {
        if (dataType == DataType.IN) {
            return this.defaultDataModeIN;
        } else if (dataType == DataType.OUT) {
            return this.defaultDataModeOUT;
        } else {
            throw new IllegalArgumentException("Unknown DataType: " + dataType);
        }
    }

    public void setClientExtendedEventHandler(String handler) {
        this.clientExtendedEventHandlerString = handler;
        logger.finest("Set to " + handler);
    }

    public String getClientExtendedEventHandler() {
        return this.clientExtendedEventHandlerString;
    }

    private void loadApplicationClasses() throws Exception {
        if (this.getApplicationJarPath() != null && this.getClassLoader() == null) {
            this.setClassLoader(ClassUtil.getClassLoader(this.getApplicationJarPath()));
            if (this.adminServer != null) {
                this.adminServer.getServer().setClassLoader(this.getClassLoader());
            }
        }

    }

    public static String getPID() {
        return pid;
    }

    public boolean isRawCommunicationLogging() {
        return this.rawCommunicationLogging;
    }

    public void setRawCommunicationLogging(boolean rawCommunicationLogging) {
        this.rawCommunicationLogging = rawCommunicationLogging;
    }

    public int getRawCommunicationMaxLength() {
        return this.rawCommunicationMaxLength;
    }

    public void setRawCommunicationMaxLength(int rawCommunicationMaxLength) {
        this.rawCommunicationMaxLength = rawCommunicationMaxLength;
    }

    public String getUptime() {
        Date lst = this.getLastStartTime();
        StringBuilder sb = new StringBuilder();
        if (lst == null) {
            sb.append("N/A");
        } else {
            long ms = System.currentTimeMillis() - lst.getTime();
            if (ms > 86400000L) {
                sb.append(ms / 86400000L).append(" days ");
                ms %= 86400000L;
            }

            if (ms > 3600000L) {
                sb.append(ms / 3600000L).append(" hours ");
                ms %= 3600000L;
            }

            if (ms > 60000L) {
                sb.append(ms / 60000L).append(" minutes ");
                ms %= 60000L;
            }

            if (ms > 1000L) {
                sb.append(ms / 1000L).append(" seconds ");
                ms %= 1000L;
            }

            sb.append(ms + " ms");
        }

        return sb.toString();
    }
}
